package org.v2ray.rocket.proxy.widget

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.os.CountDownTimer
import android.text.TextUtils
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.annotation.ColorInt
import androidx.core.animation.doOnEnd
import androidx.core.content.res.use
import androidx.core.graphics.withClip
import java.util.Locale
import kotlin.math.hypot
import kotlin.math.max
import androidx.core.graphics.toColorInt
import org.v2ray.rocket.proxy.R

@SuppressLint("CustomViewStyleable")
class MaterialCountDownButton @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyle: Int = 0
) : View(context, attrs, defStyle) {

    companion object {
        private const val DEFAULT_INTERVAL: Long = 1000
        private const val DEFAULT_COUNT = (60 * 1000).toLong()
        private const val DEFAULT_COUNT_FORMAT = "%d"
    }

    // 业务相关
    private var mCountDownFormat = DEFAULT_COUNT_FORMAT
    private var mCdFinishText: String? = null
    private var mCount: Long = DEFAULT_COUNT
    private var mInterval: Long = DEFAULT_INTERVAL
    private var mEnableCountDown = true
    private var mCountDownTimer: CountDownTimer? = null
    private var isCountDownNow = false
    private var onClickListener: OnClickListener? = null

    // UI相关
    private var cornerRadius: Float = 24f * resources.displayMetrics.density
    @ColorInt
    private var gradientStartColor: Int = "#79c8ff".toColorInt()
    @ColorInt
    private var gradientEndColor: Int = "#a48df0".toColorInt()
    private var buttonText: String = ""
    @ColorInt
    private var buttonTextColor: Int = Color.WHITE
    private var buttonTextSize: Float = 16f * resources.displayMetrics.scaledDensity

    private val bgPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val ripplePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.WHITE
        alpha = 80
    }
    private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = buttonTextColor
        textAlign = Paint.Align.CENTER
        textSize = buttonTextSize
    }
    private var rippleRadius = 0f
    private var rippleAlpha = 80
    private var rippleX = 0f
    private var rippleY = 0f
    private var isRippling = false

    private val rectF = RectF()
    private val clipPath = Path()
    private val normalAlpha = 1f
    private val disabledAlpha = 0.5f

    init {
        context.obtainStyledAttributes(attrs, R.styleable.MaterialCommonButton).use { ta ->
            cornerRadius = ta.getDimension(R.styleable.MaterialCommonButton_cornerRadius, cornerRadius)
            gradientStartColor = ta.getColor(R.styleable.MaterialCommonButton_gradientStartColor, gradientStartColor)
            gradientEndColor = ta.getColor(R.styleable.MaterialCommonButton_gradientEndColor, gradientEndColor)
            buttonText = ta.getString(R.styleable.MaterialCommonButton_buttonText) ?: ""
            buttonTextColor = ta.getColor(R.styleable.MaterialCommonButton_buttonTextColor, buttonTextColor)
            buttonTextSize = ta.getDimension(R.styleable.MaterialCommonButton_buttonTextSize, buttonTextSize)
        }
        context.obtainStyledAttributes(attrs, R.styleable.CountDownButton).use { ta ->
            mCountDownFormat = ta.getString(R.styleable.CountDownButton_countDownFormat) ?: DEFAULT_COUNT_FORMAT
            mCdFinishText = ta.getString(R.styleable.CountDownButton_cdFinishText)
            if (ta.hasValue(R.styleable.CountDownButton_countDown)) {
                mCount = ta.getFloat(R.styleable.CountDownButton_countDown, DEFAULT_COUNT.toFloat()).toInt().toLong()
            }
            mInterval = ta.getFloat(
                R.styleable.CountDownButton_countDownInterval,
                DEFAULT_INTERVAL.toFloat()
            ).toInt().toLong()
            mEnableCountDown = mCount > mInterval && ta.getBoolean(
                R.styleable.CountDownButton_enableCountDown,
                true
            )
        }
        // 初始化倒计时Timer
        if (mCountDownTimer == null) {
            mCountDownTimer = object : CountDownTimer(mCount, mInterval) {
                override fun onTick(millisUntilFinished: Long) {
                    buttonText = String.format(Locale.CHINA, mCountDownFormat, millisUntilFinished / 1000)
                    invalidate()
                }
                override fun onFinish() {
                    onCountDownFinish()
                }
            }
        }
        isClickable = true
        isFocusable = true
        alpha = normalAlpha
    }

    override fun setOnClickListener(l: OnClickListener?) {
        this.onClickListener = l
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                startRipple(event.x, event.y)
            }
            MotionEvent.ACTION_UP -> {
                endRipple()
                val rect = Rect()
                this.getGlobalVisibleRect(rect)
                if (onClickListener != null && rect.contains(event.rawX.toInt(), event.rawY.toInt())) {
                    onClickListener!!.onClick(this)
                }
                if (mEnableCountDown && rect.contains(event.rawX.toInt(), event.rawY.toInt())) {
                    isEnabled = false
                    alpha = disabledAlpha // 置灰
                    mCountDownTimer!!.start()
                    isCountDownNow = true
                }
            }
            MotionEvent.ACTION_CANCEL -> {
                endRipple()
            }
        }
        return super.onTouchEvent(event)
    }

    private fun startRipple(x: Float, y: Float) {
        rippleX = x
        rippleY = y
        val maxRadius = hypot(
            max(x, width - x),
            max(y, height - y)
        )
        val animator = ValueAnimator.ofFloat(0f, maxRadius).apply {
            setDuration(500)
            addUpdateListener {
                rippleRadius = it.animatedValue as Float
                rippleAlpha = (80 * (1 - it.animatedFraction)).toInt()
                isRippling = true
                invalidate()
            }
            doOnEnd {
                isRippling = false
                invalidate()
            }
        }
        animator.start()
    }

    private fun endRipple() {
        isRippling = false
        invalidate()
    }

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) {
        rectF.set(0f, 0f, width.toFloat(), height.toFloat())
        clipPath.reset()
        clipPath.addRoundRect(rectF, cornerRadius, cornerRadius, Path.Direction.CW)
        canvas.withClip(clipPath) {
            // 渐变背景
            bgPaint.shader = LinearGradient(
                0f, 0f, width.toFloat(), 0f,
                gradientStartColor, gradientEndColor, Shader.TileMode.CLAMP
            )
            drawRoundRect(rectF, cornerRadius, cornerRadius, bgPaint)
            // 水波
            if (isRippling) {
                ripplePaint.alpha = rippleAlpha
                drawCircle(rippleX, rippleY, rippleRadius, ripplePaint)
            }
            // 文字
            if (buttonText.isNotEmpty()) {
                textPaint.color = buttonTextColor
                textPaint.textSize = buttonTextSize
                val fontMetrics = textPaint.fontMetrics
                val baseLine = height / 2f - (fontMetrics.ascent + fontMetrics.descent) / 2
                drawText(buttonText, width / 2f, baseLine, textPaint)
            }
        }
    }

    // 公开方法支持代码设置
    fun setCornerRadius(radius: Float) {
        cornerRadius = radius
        invalidate()
    }

    fun setGradientColors(@ColorInt startColor: Int, @ColorInt endColor: Int) {
        gradientStartColor = startColor
        gradientEndColor = endColor
        invalidate()
    }

    fun setButtonText(text: String) {
        buttonText = text
        invalidate()
    }

    fun setButtonTextColor(@ColorInt color: Int) {
        buttonTextColor = color
        textPaint.color = color
        invalidate()
    }

    fun setButtonTextSize(sizeSp: Float) {
        buttonTextSize = sizeSp * resources.displayMetrics.scaledDensity
        textPaint.textSize = buttonTextSize
        invalidate()
    }

    fun setEnableCountDown(enableCountDown: Boolean) {
        mEnableCountDown = mCount > mInterval && enableCountDown
    }

    fun setCountDownFormat(countDownFormat: String?) {
        mCountDownFormat = countDownFormat!!
    }

    fun setCount(count: Long) {
        mCount = count
    }

    fun setInterval(interval: Long) {
        mInterval = interval
    }

    fun isCountDownNow(): Boolean {
        return isCountDownNow
    }

    fun setCountDown(count: Long, interval: Long, countDownFormat: String?) {
        mCount = count
        mCountDownFormat = countDownFormat!!
        mInterval = interval
        setEnableCountDown(true)
    }

    fun setCDFinishText(cdFinishText: String?) {
        mCdFinishText = cdFinishText
    }

    fun removeCountDown() {
        if (mCountDownTimer != null) {
            mCountDownTimer!!.cancel()
        }
        isCountDownNow = false
        buttonText = mCdFinishText ?: buttonText
        isEnabled = true
        alpha = normalAlpha // 恢复原色
        invalidate()
    }

    override fun setEnabled(enabled: Boolean) {
        if (isCountDownNow()) {
            return
        }
        super.setEnabled(enabled)
        isClickable = enabled
        alpha = if (enabled) normalAlpha else disabledAlpha
    }

    override fun onDetachedFromWindow() {
        removeCountDown()
        super.onDetachedFromWindow()
    }

    // 在倒计时结束时恢复按钮可用和原色
    private fun onCountDownFinish() {
        isCountDownNow = false
        isEnabled = true
        alpha = normalAlpha
        buttonText = mCdFinishText ?: buttonText
        invalidate()
    }
} 